
const React = {};
const ReactDOM = {};
class Component {
    constructor(props){
        this.props = props;
    }
    setState(partialState,cb){
        batchUpdater.stateQueue.push(partialState);
        cb && batchUpdater.cbQueue.push(cb);
        batchUpdater.dirtyComponents.push(this);
    }
    updateComponent(allState){
        Object.assign(this.state, allState);
        const new_element = this.render();
        const { _inner_element } = this;
        const patches = compareElement(new_element, _inner_element);
        if(patches.length){
            applyPatches(patches);
        }else{
            //no diff
            return ;
        }
    }
}
React.Component = Component;
//return object
React.createElement = function(type,props,...children){
    props = props || {};
    props.children = arguments.length === 3 ? children[0] : children;
    const {key = null,...other} = props; //最新版的chrome已经支持这个语法了，但是babel居然要 transform-object-rest-spread 才能支持
    return {
        type,
        props:other,
        key,
        _inst:null,
        _inner_element:null,
        _dom:null,
        _renderOne:null
    }
}

const batchUpdater = {
    isUpdating:false,
    stateQueue:[],
    cbQueue:[],
    dirtyComponents:[],
    open(){
        batchUpdater.isUpdating = false;
    },
    close(){
        batchUpdater.isUpdating = true;
        var allState = batchUpdater.stateQueue.reduce((prev,state)=>{
            return Object.assign(prev,state);
        });
        batchUpdater.dirtyComponents.forEach(comp=>{
            comp.updateComponent(allState)
        });
        batchUpdater.cbQueue.forEach((fn,idx)=>{
            fn.call(batchUpdater.dirtyComponents[idx]);
        });
    },
    wrapper:function(fn){
        return function(e){
            batchUpdater.open();
            fn(e);
            batchUpdater.close();
        }
    }
}


function setDomStyleProps(dom, style){
    Object.assign(dom.style, style);
    if( typeof style.width === 'number'){
        dom.style.width = style.width + 'px';
    }
}

//渲染一个组件，输入虚拟dom，输出真实dom
function renderOne(element){
    var dom
    if(typeof element === 'string' || typeof element === 'number'){
        dom = document.createTextNode(element);
    }else if(typeof element === 'object'){
        if(typeof element.type === 'string'){
            dom = document.createElement(element.type);
            if(element.id) dom.id = element.id;
            if(element.key) dom.key = element.key;
            const { props } = element;
            if(props.style){
                //此处要建立一个css in js 和 css prop 的对应关系，一般是建立一个字典，然后有特殊的特殊处理，鉴于时间问题先省略
                setDomStyleProps(dom, props.style);
            }
            props.type && dom.setAttribute('type',props.type);
            props.checked &&  dom.setAttribute('checked',!!props.checked);
            if(props.onClick){
                //react中是使用合成事件的，鉴于时间问题先省略
                dom.addEventListener('click',batchUpdater.wrapper(props.onClick));
            }
            if(typeof props.children !== 'undefined'){
                if(props.children.forEach){
                    props.children.forEach(child=>render(child, dom));
                } else{
                    render(props.children, dom);
                }
            }
            element._dom = dom;
            element._renderOne = renderOne;
        }else if(typeof element.type === 'function'){
            const inst = new element.type(element.props);
            const inner_element = inst.render();
            dom = renderOne(inner_element);
            inst._inner_element = inner_element;
            // element._inst = inst;
            inst._dom = dom;
            inst._renderOne = renderOne;
        }else {
            const inst = Object.assign({}, element.type);
            inst.props=element.props;
            const inner_element = inst.render();
            dom = renderOne(inner_element);
            inst._inner_element = inner_element;
            // element._inst = inst;
            inst._dom = dom;
            inst._renderOne = renderOne;
        }
    }
    return dom;
}

//把一个虚拟dom挂载到一个真实dom里面
function render(element,mountNode){
    mountNode.appendChild(renderOne(element));
}

ReactDOM.render = render;





const allArr = function(){
    let r = [];
    for(let i = 1 ; i<= 20; i++){
        r.push(i);
    }
    return r;
}()
class BHelloMessage extends React.Component {
    constructor(props) {
        super(props)
        this.state = {
            list: allArr.slice(),
            a:true
        }
        this.render=this.render;
        this.setState=this.setState;
        this.updateComponent=this.updateComponent;
    }
    render() {
        const {list,a} = this.state;
        return (
            <div>
            <p>Hello {this.props.name}</p>
        <ul>
        {
            list.map(i=><li key={i}>{i}</li>)
    }
    </ul>
        <span>a: {''+a}</span>
        <span>{list[0]}{list[1]}</span>
        <p style={{background:'red',width:list[0]*10+100}} id={'aaa'+list[0]}>a</p>
            <button onClick={() => {
            this.setState({
                a: !this.state.a
            });
            console.log(this.state.a);
            let arr = allArr.slice();
            arr = arr.filter(item=>Math.random()>0.5)
            arr.sort((a,b)=>{
                return Math.random()-0.5;
            });
            window.arr = arr;
            // const arr = [5, 7, 11, 17, 12, 19];
            console.log(this.state.list, arr);
            this.setState({
                list: arr
            },function(){
                console.log(this.state);
            });
        }}>Random change</button>
        </div>
    );
    }
}
let CC =new BHelloMessage ()
ReactDOM.render(
<CC name="Taylor" >xxxx</CC>,
    document.getElementById('root')
);
